package com.yuw.utils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class MyUtils {

	/**
	 * 将查询结果集转换为List+Bean形式
	 * 
	 * @param <T>
	 *            实体列的Class泛型
	 * 
	 * @param rs
	 *            查询结果集
	 * @return beanlist
	 */
	public static <T> List<T> convertResultSet2BeanList(ResultSet rs, Class<T> clazz) {
		// 返回值
		List<T> lst = new ArrayList<>();
		if (rs != null) {
			try {
				// 因为已经遍历过一次结果，所有再次遍历之前，需要将光标移动到最前位置（第一行之前）
				rs.beforeFirst();
				// 获取结果集中的所有的列的信息
				ResultSetMetaData rsmd = rs.getMetaData();
				// 获取结果集中列的个数
				int colCount = rsmd.getColumnCount();
				// 此处应该遍历打印一下列标题
				while (rs.next()) {
					// 创建存储当前行的bean对象
					T tBean = MyUtils.getInstance(clazz);
					// 遍历当前行的每列的信息
					for (int i = 1; i <= colCount; i++) {
						// 取出每一列的列名
						String strColName = rsmd.getColumnLabel(i);
						/*
						 * 注意：需要遵循约定规则：实体类的属性名和数据库的字段名名字要一样，且属性名要全部小写
						 */
						// 反射：通过列名获取当前实例类的属性对象
						Field field = clazz.getDeclaredField(strColName.toLowerCase());
						// 反射：设置私有属性的操作权限
						field.setAccessible(true);
						// 反射：调用field的set方法进行属性赋值
						field.set(tBean,
								convertJDBCDataType2JavaDataType(rs.getObject(strColName), field.getType().getName()));
					}
					// 将当前行的实体对象存入list中
					lst.add(tBean);
				}

			} catch (Exception e) {
				// 将查询结果集转换为List对象异常：
				System.out.println("将查询结果集转换为List对象异常：" + e.getMessage());
				e.printStackTrace();
			}
		}

		return lst;

	}

	/**
	 * 把数据映射为的JDBC数据类型转换常用java基本数据类型
	 * 
	 * @param obj
	 *            数据映射为的JDBC数据类型
	 * @param strDesDataType
	 *            常用java基本数据类型
	 * @return 转换之后的数据类型
	 */
	private static Object convertJDBCDataType2JavaDataType(Object obj, String strDesDataType) {
		// 返回值类型
		Object obj_re = null;
		if (obj != null) {
			// 将不能映射为java基本类型的JDBC数据类型转为与之对应的java类型
			// 类型转换
			switch (strDesDataType.trim()) {
			case "java.lang.Long":
				obj_re = Long.parseLong(obj.toString());
				break;
			case "java.lang.Double":
				obj_re = Double.parseDouble(obj.toString());
				break;
			// ... 追加补充其他类型的转换

			// 不需要进行转换的数据类型直接返回即可
			default:
				obj_re = obj;
			}
		}
		// 返回值
		return obj_re;

	}

	/**
	 * 将查询结果集转何为List
	 * 
	 * @param rs
	 *            查询结果集
	 * @return List结果
	 */
	public static List<Map<String, Object>> convertResultSet2List(ResultSet rs) {
		List<Map<String, Object>> lst = new ArrayList<>();
		if (rs != null) {
			try {
				// 因为已经遍历过一次结果，所有再次遍历之前，需要将光标移动到最前位置（第一行之前）
				rs.beforeFirst();
				// 获取结果集中的所有的列的信息
				ResultSetMetaData rsmd = rs.getMetaData();
				// 获取结果集中列的个数
				int colCount = rsmd.getColumnCount();
				// 此处应该遍历打印一下列标题
				while (rs.next()) {
					// 创建存储当前行的map对象【有序】
					Map<String, Object> mapRow = new LinkedHashMap<>();
					// 遍历当前行的每列的信息
					for (int i = 1; i <= colCount; i++) {
						// 取出每一列的列名
						String strColName = rsmd.getColumnLabel(i);
						// 通过列名获取当前行当前列的值
						// 将当前类的值存入map中
						mapRow.put(strColName, rs.getObject(strColName));
					}
					// 将当前行的map存入list中
					lst.add(mapRow);
				}
			} catch (SQLException e) {
				// 将查询结果集转换为List对象异常：
				System.out.println("将查询结果集转换为List对象异常：" + e.getMessage());
				e.printStackTrace();
			}
		}
		return lst;
	}

	/**
	 * 简单工厂模式：获取一个指定Class的实例对象
	 * 
	 * @param clazz
	 *            Class
	 * @return 实例对象
	 */
	public static <T> T getInstance(Class<T> clazz) {
		// 返回值
		T t = null;
		try {
			// 反射获取该Class的一个实例对象
			t = clazz.newInstance();
		} catch (Exception e) {
			// 获取实例对象异常
			System.out.println("获取实例对象异常:" + e.getMessage());
			e.printStackTrace();
		}
		return t;
	}
}
